#ifndef __M_ROUTE_H__
#define __M_ROUTE_H__
#include"../mqcommon/mq_msg.pb.h"
#include"../mqcommon/helper.hpp"
#include"../mqcommon/logger.hpp"

namespace mq{
    class Router{
        public:
            static bool IsLegalRoutingkey(const std::string& routingkey){
                for(auto& ch : routingkey){
                    if((ch >= '0' && ch <= '9')||
                    (ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z')||
                    (ch == '.') || (ch == '_'))
                        continue;
                    return false;
                }
                return true;
            }

            static bool IsLegalBindingkey(const std::string& Bindingkey){
                for(auto& ch : Bindingkey){
                    if((ch >= '0' && ch <= '9')||
                    (ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z')||
                    (ch == '#')|| (ch == '*') || (ch == '.') || (ch == '_'))
                        continue;
                    return false;
                }
                std::vector<std::string> vs;
                Stringsplit::split(Bindingkey,&vs,".");
                for(auto& subword : vs){
                    if((subword.size()>1) && 
                        ((subword.find('#') != std::string::npos) 
                        || (subword.find('*') != std::string::npos)))
                        return false;
                }
                for(int i =1;i < vs.size();i++){
                    if(vs[i] == "#" && vs[i-1] == "*")  return false;
                    if(vs[i] == "*" && vs[i-1] == "#")  return false;
                    if(vs[i] == "#" && vs[i-1] == "#")  return false;
                }
                return true;
            }

            static bool route(ExchangeType type,const std::string& routingkey,const std::string& Bindingkey){
                if(type == ExchangeType::DIRECT) return (routingkey == Bindingkey);
                else if(type == ExchangeType::FAOUT) return true;
                else{
                    std::vector<std::string> rsubwrod;
                    Stringsplit::split(routingkey,&rsubwrod,".");

                    std::vector<std::string> bsubwrod;
                    Stringsplit::split(Bindingkey,&bsubwrod,".");
                    // LOG_DEBUG("testing split done");   
                    std::vector<std::vector<bool>> vvb(Bindingkey.size()+1,std::vector<bool>(routingkey.size()+1,false));
                    vvb[0][0] = true;
                    // LOG_DEBUG("topic doing...");   
                    for(int i = 1;i <= bsubwrod.size();i++){          //j
                        for(int j = 1;j <= rsubwrod.size();j++){   //i
                            if(bsubwrod[0] == "#") 
                                vvb[1][0] = true;
                            if(bsubwrod[i-1] == rsubwrod[j-1] || (bsubwrod[i-1] == "*")) vvb[i][j] = vvb[i-1][j-1];
                            if(bsubwrod[i-1] == "#") vvb[i][j] = vvb[i-1][j-1] || vvb[i-1][j] || vvb[i][j-1];
                        }
                    }
                    if(vvb[bsubwrod.size()][rsubwrod.size()] == true)   return true;
                    return false;
                }
            }
    };


}


#endif